/**
 * 
 */
package de.nak.fireDepartment.service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Collection;
import java.util.LinkedList;

import javax.servlet.ServletContext;

import org.apache.log4j.Logger;
import org.apache.struts.upload.FormFile;

import de.nak.fireDepartment.exceptions.ImageUploadException;
import de.nak.fireDepartment.logger.MyLog4JLogger;

/**
 * Implementation of ImageUploadService Interface
 * @author Sven Redelin
 *
 */
public class ImageUploadServiceImpl implements ImageUploadService {

	private Logger logger;
	
	/**
	 * The Contructor gets the Logger and creates a Message
	 */
	public ImageUploadServiceImpl(){
		logger = MyLog4JLogger.getLogger();
		logger.info("Instance of ImageUploadServiceImpl has been created");
	}
	
	/**
	 * Identifier for pictures starts with 200 and increased by every image upload.
	 * This identifier will be reseted by restarting the server.
	 */
	private long uniqueFileID = 200;
	
	/** {@inheritDoc} */
	public String uploadFile(FormFile aFile, String fileType, ServletContext servletContext) throws ImageUploadException {
        logger.info("A File should be uploaded");
		try{
			logger.info("Get File-Details");
			// get the file-Details
			String fileMimeType = aFile.getContentType();
	        String fileName    = aFile.getFileName();
	        int fileSize       = aFile.getFileSize();
	        byte[] fileData    = aFile.getFileData();
	        
	        // if a file is selected, the file-Size is bigger than zero
	        if(fileSize > 0){
	        	logger.info("Check the file-Details");
	        	// check mime-Type
		        checkMimeType(fileMimeType);
		        // check file-Size
		        checkFileSize(fileSize);
		        
		        // get the image-upload-folder on the server
		        String imageUploadFolder = getImageUploadFolder(fileType);
				
		        // get the refactored FileName
				String newFileName = optimizeFileName(fileName);
				// get the indirect Web path
				String internalWebServerPath = "/images/uploads/" + imageUploadFolder + "/" + newFileName;
				// get the direct server path
				String realWebserverPath = servletContext.getRealPath( internalWebServerPath );
				// Create new File with real Webserver Path
				File newFile = new File(realWebserverPath);
				// Create new FileOutputStream
				FileOutputStream fos = new FileOutputStream(newFile);
				// write file Data from FormFile
				fos.write(fileData);
				fos.close();
				logger.info("File Upload was successfully");
				// return Webpath to the image
				return "/FireDepartmentManagement" + internalWebServerPath;
	        }else{
	        	// if no file is selected return an empty string
	        	return "";
	        }
		}catch (IOException ex) {
			logger.error(ex.getMessage());
			throw new ImageUploadException(ex.getMessage());
		}
	}

	/** {@inheritDoc} */
	public void deleteImage(String relativeImagePath, ServletContext servletContext) throws ImageUploadException{
		logger.info("Image should be deleted");
		
		// if there's a path to a file, delete the file
		if(relativeImagePath!=null && !relativeImagePath.equals("")){
			// Delete "/FireDepartmentManagement" of relativeImagePath and get Serverpath
			String realWebserverPath = servletContext.getRealPath(relativeImagePath.substring(25));
			// create new File-Object with the pointer in the image
			File aFile = new File(realWebserverPath);
			// delete File
			boolean imageDeleted = aFile.delete();
			
			// if file can't be deleted, display the error
			if(!imageDeleted){
				logger.error("Image can't be deleted!");
				throw new ImageUploadException("Image can't be deleted");
			}
			logger.info("Image successfully deleted!");
		}else{
			logger.info("No image to delete");
		}
	}
	
	/**
	 * Check the mime-Type of the file
	 * @param mimeType
	 * @throws ImageUploadException
	 */
	private void checkMimeType(String mimeType) throws ImageUploadException{
		// initiate Flag
		boolean mimeTypeValid = false;
		// loop over allowed mime-Types and compare with the given
        for (String allowedMimeType : getAllowedMimeTypes()) {
			if(mimeType.equals(allowedMimeType))
				mimeTypeValid = true;
		}
        // if flag is "false" throw Exception
        if(!mimeTypeValid){
        	throw new ImageUploadException("text.error.mimeType");
        }
	}
	
	/**
	 * Check the file Size
	 * @param fileSize
	 * @throws ImageUploadException
	 */
	private void checkFileSize(int fileSize) throws ImageUploadException{
		// if the file size is bigger 100kb throw exception
		if(fileSize > 100000)
        	throw new ImageUploadException("text.error.fileSize");

	}
	
	/**
	 * Gets the Image-Upload-Folder
	 * @param fileType
	 * @return String
	 * @throws ImageUploadException
	 */
	private String getImageUploadFolder(String fileType) throws ImageUploadException{
		if(fileType == ImageUploadService.DEPARTMENT){
			return "departments";
		}else if(fileType == ImageUploadService.CAR){
			return "cars";
		}else if(fileType == ImageUploadService.EQUIPMENT){
			return "equipments";
		}else{
			throw new ImageUploadException("Wrong File-Type or File-Type not set!");
		}
	}
	
	/**
	 * Optimize the FileName
	 * @param fileName
	 * @return String
	 */
	private String optimizeFileName(String fileName){
		// replace blanks
		String newFileName = fileName.replace(" ", "");
		// set the unique ID for Image
		newFileName = generateUniqueImageID() + "_" + newFileName;
		return newFileName;
	}
	
	/**
	 * get the allowed MimeTypes
	 * @return Collection<String>
	 */
	private Collection<String> getAllowedMimeTypes(){
		Collection<String> mimeTypes = new LinkedList<String>();
		mimeTypes.add("image/gif");
		mimeTypes.add("image/jpeg");
		mimeTypes.add("image/pjpeg");
        
		return mimeTypes;
	}
	
	/**
	 * Gets the unique File ID
	 * @return long
	 */
	private long generateUniqueImageID(){
		// if the function is called the uniqueFileID will be increased
		return uniqueFileID++;
	}
	
	
	
}
